package com.easyaop.test.core.listener;

import net.bytebuddy.agent.builder.AgentBuilder;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.utility.JavaModule;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * @author lipan
 * @since 2025-01-20
 */
public class DebugAgentListener implements AgentBuilder.Listener {
    public static final String DEBUG_LOCATION_PROPERTY = "easy-aop.debugLocation";

    private static String debugLocation;

    @Override
    public void onDiscovery(String s, ClassLoader classLoader, JavaModule javaModule, boolean b) {
        //System.out.println(s);
    }

    @Override
    public void onTransformation(TypeDescription typeDescription, ClassLoader classLoader, JavaModule javaModule,
                                 boolean b, DynamicType dynamicType) {
        if (debugLocation != null) {
            dump(typeDescription.getName(), dynamicType.getBytes());
        }
    }

    @Override
    public void onIgnored(TypeDescription typeDescription, ClassLoader classLoader, JavaModule javaModule, boolean b) {

    }

    @Override
    public void onError(String s, ClassLoader classLoader, JavaModule javaModule, boolean b, Throwable throwable) {
        System.err.println(s + "error: " + throwable.getMessage());
    }

    @Override
    public void onComplete(String s, ClassLoader classLoader, JavaModule javaModule, boolean b) {
        //System.out.println(s);
    }

    public static void dump(String name, byte[] bytes) {
        String dirs = name.replace('.', File.separatorChar);
        new File(debugLocation + File.separator + dirs).getParentFile().mkdirs();
        File file = new File(debugLocation + File.separator + dirs + ".class");
        System.out.println(file.getPath());
        try (BufferedOutputStream stream = new BufferedOutputStream(new FileOutputStream(file))) {
            stream.write(bytes);
        } catch (IOException ex) {
            throw new RuntimeException(ex);
        }
    }

    static {
        debugLocation = System.getProperty(DEBUG_LOCATION_PROPERTY);
    }
}
